package GUI;

import java.util.Vector;

import org.jfree.data.DomainInfo;
import org.jfree.data.Range;
import org.jfree.data.RangeInfo;
import org.jfree.data.xy.AbstractXYDataset;
import org.jfree.data.xy.XYDataset;

import Statistics.IDGraphGlobalProperty;
import Statistics.IDGraphGlobalProperty.DegreeRecord;

public class DegreeDistributionDataSet extends AbstractXYDataset implements
		XYDataset, DomainInfo, RangeInfo {
	// Two series: in-degree and out-degree
	private static final int DEFAULT_SERIES_COUNT = 2;
	private static final int DEFAULT_ITEM_COUNT = 1000;
	private static final double DEFAULT_RANGE = 1000.0D;

	private Double[][] xValues;
	private Double[][] yValues;
	private int seriesCount;
	private int itemCount;
	private Number domainMin;
	private Number domainMax;
	private Number rangeMin;
	private Number rangeMax;
	private Range domainRange;
	private Range range;

	public DegreeDistributionDataSet() {
		this(DEFAULT_SERIES_COUNT, DEFAULT_ITEM_COUNT);
	}

	public DegreeDistributionDataSet(IDGraphGlobalProperty idGP)
	{
		Vector<DegreeRecord> in  = idGP.GetInDegreeDistribution();
		Vector<DegreeRecord> out = idGP.GetOutDegreeDistribution();
		int maxItemCount = in.size()>out.size()?in.size():out.size();
		
		this.xValues = new Double[DEFAULT_SERIES_COUNT][maxItemCount];
		this.yValues = new Double[DEFAULT_SERIES_COUNT][maxItemCount];
		this.seriesCount = DEFAULT_SERIES_COUNT;
		this.itemCount   = maxItemCount;
		
		double d1 = (1.0D / 0.0D);
		double d2 = (-1.0D / 0.0D);
		double d3 = (1.0D / 0.0D);
		double d4 = (-1.0D / 0.0D);
		
		int index = 0;
		for(DegreeRecord dr:in)
		{
			double d5 = (double)dr.degree;
			this.xValues[0][index] = d5;
			if (d5 < d1)
				d1 = d5;
			if (d5 > d2)
				d2 = d5;
			double d6 =  (double)dr.count;
			this.yValues[0][index++] = d6;
			if (d6 < d3)
				d3 = d6;
			if (d6 <= d4)
				continue;
			d4 = d6;
			
		}
		index = 0;
		for(DegreeRecord dr:out)
		{
			double d5 = (double)dr.degree;
			this.xValues[1][index] = d5;
			if (d5 < d1)
				d1 = d5;
			if (d5 > d2)
				d2 = d5;
			double d6 =  (double)dr.count;
			this.yValues[1][index++] = d6;
			if (d6 < d3)
				d3 = d6;
			if (d6 <= d4)
				continue;
			d4 = d6;
		}
		
		this.domainMin = new Double(in.get(0).degree);
		this.domainMax = new Double(in.lastElement().degree);
		this.domainRange = new Range(d1, d2);
		this.rangeMin = new Double(d3);
		this.rangeMax = new Double(d4);
		this.range = new Range(d3, d4);
		
	}
	
	public DegreeDistributionDataSet(int paramInt1, int paramInt2) {
		this.xValues = new Double[paramInt1][paramInt2];
		this.yValues = new Double[paramInt1][paramInt2];
		this.seriesCount = paramInt1;
		this.itemCount = paramInt2;
		double d1 = (1.0D / 0.0D);
		double d2 = (-1.0D / 0.0D);
		double d3 = (1.0D / 0.0D);
		double d4 = (-1.0D / 0.0D);
		for (int i = 0; i < paramInt1; ++i)
			for (int j = 0; j < paramInt2; ++j) {
				double d5 = (Math.random() - 0.5D) * 200.0D;
				this.xValues[i][j] = new Double(d5);
				if (d5 < d1)
					d1 = d5;
				if (d5 > d2)
					d2 = d5;
				double d6 = (Math.random() + 0.5D) * 6.0D * d5 + d5;
				this.yValues[i][j] = new Double(d6);
				if (d6 < d3)
					d3 = d6;
				if (d6 <= d4)
					continue;
				d4 = d6;
			}
		this.domainMin = new Double(d1);
		this.domainMax = new Double(d2);
		this.domainRange = new Range(d1, d2);
		this.rangeMin = new Double(d3);
		this.rangeMax = new Double(d4);
		this.range = new Range(d3, d4);
	}

	@Override
	public int getSeriesCount() {
		// TODO Auto-generated method stub
		return seriesCount;
	}

	@Override
	public Comparable getSeriesKey(int series) {
		// TODO Auto-generated method stub
		return series==0?"In Degree ":"Out Degree";
	}

	@Override
	public int getItemCount(int series) {
		// TODO Auto-generated method stub
		return this.itemCount;
	}

	@Override
	public Number getX(int series, int item) {
		// TODO Auto-generated method stub
		return this.xValues[series][item];
	}

	@Override
	public Number getY(int series, int item) {
		// TODO Auto-generated method stub
		return this.yValues[series][item];
	}

	@Override
	public Range getDomainBounds(boolean includeInterval) {
		// TODO Auto-generated method stub
		return this.domainRange;
	}

	@Override
	public double getDomainLowerBound(boolean includeInterval) {
		// TODO Auto-generated method stub
		return this.domainMin.doubleValue();
	}

	@Override
	public double getDomainUpperBound(boolean includeInterval) {
		// TODO Auto-generated method stub
		return this.domainMax.doubleValue();
	}

	@Override
	public Range getRangeBounds(boolean includeInterval) {
		// TODO Auto-generated method stub
		return this.range;
	}

	@Override
	public double getRangeLowerBound(boolean includeInterval) {
		// TODO Auto-generated method stub
		return this.rangeMin.doubleValue();
	}

	@Override
	public double getRangeUpperBound(boolean includeInterval) {
		// TODO Auto-generated method stub
		return this.rangeMax.doubleValue();
	}

}
